package com.example.calculator;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private int[] idNum = {R.id.button_0, R.id.button_1, R.id.button_2, R.id.button_3,
            R.id.button_4, R.id.button_5, R.id.button_6, R.id.button_7, R.id.button_8, R.id.button_9};
    private int[] idCal = {R.id.button_add, R.id.button_sub, R.id.button_mul, R.id.button_div,R.id.button_left,
            R.id.button_right,R.id.button_point,R.id.button_del,R.id.button_cle,R.id.button_equ};
    private Button[] buttonsCal = new Button[idCal.length];
    private Button[] buttonsNum = new Button[idNum.length];
    private EditText input ;
    private TextView output;
    private String Text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        input = findViewById(R.id.input);
        input.setText("");
        input.setEnabled(false);
        output = findViewById(R.id.output);
        output.setText("");

        for (int i = 0; i < idCal.length; i++) {
            buttonsCal[i] =  findViewById(idCal[i]);
            buttonsCal[i].setOnClickListener(new CalOnClick());
        }
        for (int i = 0; i < idNum.length; i++) {
            buttonsNum[i] = findViewById(idNum[i]);
            buttonsNum[i].setOnClickListener(new NumberOnClick());
        }
    }

    class NumberOnClick implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            if (!output.getText().toString().equals("")) {
                input.setText("");
                output.setText("");
            }
            switch (v.getId())
            {
                case R.id.button_0: input.append("0");break;
                case R.id.button_1: input.append("1");break;
                case R.id.button_2: input.append("2");break;
                case R.id.button_3: input.append("3");break;
                case R.id.button_4: input.append("4");break;
                case R.id.button_5: input.append("5");break;
                case R.id.button_6: input.append("6");break;
                case R.id.button_7: input.append("7");break;
                case R.id.button_8: input.append("8");break;
                case R.id.button_9: input.append("9");break;
            }
        }
    }
    class CalOnClick implements  View.OnClickListener{
        @Override
        public void onClick(View v) {
            if (!output.getText().toString().equals("")) {
                input.setText("");
                output.setText("");
            }
            switch (v.getId())
            {
                case R.id.button_add:input.append("+");break;
                case R.id.button_sub:input.append("-");break;
                case R.id.button_mul:input.append("*");break;
                case R.id.button_div:input.append("/");break;
                case R.id.button_left:input.append("(");break;
                case R.id.button_right:input.append(")");break;
                case R.id.button_point:input.append(".");break;
                case R.id.button_del:
                    if (!input.getText().toString().isEmpty() ) {
                        Text = input.getText().toString();
                        Text = Text.substring(0, Text.length() - 1);
                        input.setText(Text);
                    }break;
                case R.id.button_cle: input.setText("");output.setText("");break;
                case R.id.button_equ: output.setText(new Calculate(input.getText().toString()).result);break;
            }
        }
    }

    public class Calculate {
        StringBuilder result;
        public Calculate(String m) {
            try {
                List<String> list=new ArrayList();
                Pattern p = Pattern.compile("[\\+\\-/\\*()]|\\d+\\.?\\d*");
                Matcher k = p.matcher(m);
                while(k.find()){
                    list.add(k.group());
                }
                List<String> HZLIST=this.Change(list);
                this.JSHZ(HZLIST);
            } catch (Exception e) {
                result.delete(0, result.length());
                result.append("未知错误");
            }
        }

        public List<String> Change(List<String> list){
            List<String> HZLIST=new ArrayList();
            Stack<String> stack=new Stack();
            for(String str:list){
                int flag=this.PiPei(str);
                switch (flag) {
                    case 1:
                        stack.push(str);
                        break;
                    case 2:
                        String pop=stack.pop();
                        while(!pop.equals("(")){
                            HZLIST.add(pop);
                            pop=stack.pop();
                        }
                        break;
                    case 3:
                        HZLIST.add(str);
                        break;
                    case 4:
                        if(stack.isEmpty()){
                            stack.push(str);
                            break;
                        }
                        else{
                            if(stack.peek().equals("(")){
                                stack.push(str);
                                break;
                            }else{
                                int J1=this.YXJ(str);
                                int J2=this.YXJ(stack.peek());
                                if(J1>J2){
                                    stack.push(str);
                                }else{
                                    while(!stack.isEmpty()){
                                        String f=stack.peek();
                                        if(f.equals("(")){
                                            stack.push(str);
                                            break;
                                        }else{
                                            if(this.YXJ(str)<=this.YXJ(f)){
                                                HZLIST.add(f);
                                                stack.pop();
                                            }else{
                                                stack.push(str);
                                                break;
                                            }
                                        }
                                    }
                                    if(stack.isEmpty()){
                                        stack.push(str);
                                    }
                                }
                                break;
                            }
                        }
                }
            }
            while(!stack.isEmpty()){
                HZLIST.add(stack.pop());
            }
            return HZLIST;
        }

        public int YXJ(String str){
            int YXJ;
            if(str.equals("+")||str.equals("-")){
                YXJ = 1;
            }else{
                YXJ = 2;
            }
            return YXJ;
        }

        public int PiPei(String s){
            if(s.equals("(")){
                return 1;
            }else if(s.equals(")")){
                return 2;
            }else if(s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/")){
                return 4;
            }else {
                return 3;
            }
        }

        public void JSHZ(List<String> list){
            double value;
            result = new StringBuilder();
            Stack<Double> stack=new Stack();
            for(String str:list){
                if(str.equals("+")||str.equals("-")||str.equals("*")||str.equals("/")) {
                    Double pop1 = stack.pop();
                    Double pop2 = stack.pop();
                    if(str.equals("+")){
                        value=pop2+pop1;
                    }else if(str.equals("-")){
                        value=pop2-pop1;
                    }else if(str.equals("*")){
                        value=pop2*pop1;
                    }else {
                        value=pop2/pop1;
                    }
                    stack.push(value);
                }else {
                    Double push = Double.parseDouble(str);
                    stack.push(push);
                }
            }
            if(!stack.isEmpty())
            {
                result.append(stack.pop());
            }
        }
    }
}
